import bpy, numpy

# file that contains useful blender some functions that I don't
# want to re-write on each individual .py file

# show message on screen copied the code from here
# https://b3d.interplanety.org/en/creating-pop-up-panels-with-user-ui-in-blender-add-on/
class MessageBox(bpy.types.Operator):
  bl_idname = "message.messagebox"
  bl_label = "INFORMATION:"

  message = bpy.props.StringProperty(
    name = "message",
    description = "message",
    default = ''
  )
   
  def execute(self, context):
    return {'FINISHED'} 
  def invoke(self, context, event):
    return context.window_manager.invoke_props_dialog(self, width = 400)
  def draw(self, context):
    self.layout.label("")
    self.layout.label(self.message)
    self.layout.label("")
 
bpy.utils.register_class(MessageBox)

# function to display a message using the above class
def disp_msg(string):
  print(string)
  bpy.ops.message.messagebox('INVOKE_DEFAULT', message = string)

# select object and its children
def select_obj(scene, obj, recursive):
  
  # select an area
  bpy.ops.object.select_all(action='DESELECT')
  scene.objects.active = None
  obj.select = True
  scene.objects.active = obj
  
  # select object and its children
  if (recursive == True):
    bpy.ops.object.select_grouped(type = 'CHILDREN_RECURSIVE')
    obj.select = True

# transf_apply_recurse function
# transform_apply the parent and its child meshes
# selects the parent object at the end
def transf_apply_recurse(scene, obj, loc, rot, sca):
  
  # select obj
  select_obj(scene, obj, False)
  bpy.ops.object.transform_apply(location = loc, rotation = rot, scale = sca)
  
  # armature child mesh scaling
  if (len(obj.children) != 0):
    for child in obj.children:    
      # select child and apply transform
      select_obj(scene, child, False)
      bpy.ops.object.transform_apply(location = loc, rotation = rot, scale = sca)
    
  # select parent object at the end
  select_obj(scene, obj, False)

# set a bone bind matrix
def set_bone_bind_mat(bone, mat):
  
  # custom property matrix bind_mat is column written
  temp_array = [mat[0][0], mat[1][0], mat[2][0], mat[3][0],
                mat[0][1], mat[1][1], mat[2][1], mat[3][1],
                mat[0][2], mat[1][2], mat[2][2], mat[3][2],
                mat[0][3], mat[1][3], mat[2][3], mat[3][3]] 

  # convert temp_array to the right type with numpy
  temp_array = numpy.array(temp_array, dtype = 'f')      
  bone["bind_mat"] = temp_array
  # if I don't convert temp_array to the right type
  # the exported matrices will contain weird data  
  return

# set a bone rest matrix
def set_bone_rest_mat(bone, mat):
  
  # custom property matrix rest_mat is column written
  temp_array = [mat[0][0], mat[1][0], mat[2][0], mat[3][0],
                mat[0][1], mat[1][1], mat[2][1], mat[3][1],
                mat[0][2], mat[1][2], mat[2][2], mat[3][2],
                mat[0][3], mat[1][3], mat[2][3], mat[3][3]] 

  # convert temp_array to the right type with numpy
  temp_array = numpy.array(temp_array, dtype = 'f')      
  bone["rest_mat"] = temp_array
  # if I don't convert temp_array to the right type
  # the exported matrices will contain weird data
  return
